package com.sunlg.smarthome.data.remote;

import android.text.TextUtils;
import android.widget.RelativeLayout;

import com.google.gson.Gson;
import com.sunlg.smarthome.data.entity.Curtain;
import com.sunlg.smarthome.data.entity.EnvirDevice;
import com.sunlg.smarthome.data.entity.FireDevice;
import com.sunlg.smarthome.data.entity.FireWarning;
import com.sunlg.smarthome.data.entity.Gateway;
import com.sunlg.smarthome.data.entity.Humidity;
import com.sunlg.smarthome.data.entity.Light;
import com.sunlg.smarthome.data.entity.Notification;
import com.sunlg.smarthome.data.entity.Pump;
import com.sunlg.smarthome.data.entity.RainObserver;
import com.sunlg.smarthome.data.entity.SecurityDevice;
import com.sunlg.smarthome.data.entity.SecurityWarning;
import com.sunlg.smarthome.data.entity.TempAndHum;
import com.sunlg.smarthome.data.entity.Temperature;
import com.sunlg.smarthome.data.entity.User;
import com.sunlg.smarthome.data.entity.Warning;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import okhttp3.MediaType;
import okhttp3.RequestBody;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * 服务请求包装类
 * Created by sunlg on 2017/2/22.
 */

public class SHServiceWrapper {

    private SHService shService;

    public SHServiceWrapper(){
        shService = new OKHttpUtil().getService();
    }

    //泛型有待理解

    /**
     *在IO线程上进行网络请求，在UI线程操作数据
     * @return
     */
    <T> Observable.Transformer<T, T> applySchedulers() {
        return new Observable.Transformer<T, T>() {
            @Override
            public Observable<T> call(Observable<T> observable) {
                return observable.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

    /**
     * 将请求参数转化成json格式提交
     * @param params
     * @return
     */
    private RequestBody toRequestBody(Map<String, Object> params){
        Gson gson = new Gson();
        String strEntity = gson.toJson(params);
        RequestBody body = RequestBody
                .create(MediaType
                                .parse("application/json;charset=UTF-8"),
                        strEntity);
        return body;
    }

    public void register(Map<String, Object> map, MySubscriber<Result> mySubscriber){
        shService.register(map)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void login(Map<String, Object> map, MySubscriber<Result<User>> mySubscriber){
        shService.login(map)
                .compose(this.<Result<User>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void updateUser(User user, MySubscriber<Result<User>> mySubscriber){
        Map<String, Object> map = new HashMap<>();
        map.put("id", user.getId());
        if(!TextUtils.isEmpty(user.getPassword())){
            map.put("password", user.getPassword());
        }
        if(!TextUtils.isEmpty(user.getEmail())){
            map.put("email", user.getEmail());
        }
        if(!TextUtils.isEmpty(user.getPhone())){
            map.put("phone", user.getPhone());
        }
        shService.updateUserMsg(map)
                .compose(this.<Result<User>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void logout(MySubscriber<Result> mySubscriber){
        shService.logout()
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void addLight(Light light, MySubscriber<Result> mySubscriber){
        Map<String, Object> map = new HashMap<>();
        map.put("gatewayId", light.getGatewayId());
        map.put("device", light.getDevice());
        map.put("description", light.getDescription());
        shService.addLight(map)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void deleteLight(Integer lightId, MySubscriber<Result> mySubscriber){
        shService.deleteLight(lightId)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void takeOnLight(Integer lightId, Integer level, MySubscriber<Result> mySubscriber){
        shService.takeOn(lightId, level)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void takeOff(Integer lightId, MySubscriber<Result> mySubscriber){
        shService.takeOff(lightId)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void loadAllLight(int gatewayId, MySubscriber<Result<List<Light>>> mySubscriber){
        shService.loadAllLight(gatewayId)
                .compose(this.<Result<List<Light>>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void addGateway(Map<String, Object> gateway, MySubscriber<Result> mySubscriber){
        shService.addGateway(gateway)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void deleteGateway(Integer id, MySubscriber<Result> mySubscriber){
        shService.deleteGateway(id)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void bindGateway(Gateway gateway, MySubscriber<Result> mySubscriber){
        shService.bindGateway(gateway.getNo(),
                gateway.getDescription())
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getGatewayById(Integer id, MySubscriber<Result<Gateway>> mySubscriber){
        shService.getGatewayById(id)
            .compose(this.<Result<Gateway>>applySchedulers())
            .subscribe(mySubscriber);
    }

    public void getGatewayByNo(Integer no, MySubscriber<Result<Gateway>> mySubscriber){
        shService.getGatewayByNo(no)
                .compose(this.<Result<Gateway>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getGatewayByUserId(Integer userId, MySubscriber<Result<List<Gateway>>> mySubscriber){
        shService.getGatewayByUserId(userId)
                .compose(this.<Result<List<Gateway>>>applySchedulers())
                .subscribe(mySubscriber);

    }

    public void updateGateway(Gateway gateway, MySubscriber<Result> mySubscriber){
        Map<String, Object> map = new HashMap<>();
        map.put("id", gateway.getId());
        if(gateway.getNo() != null){
            map.put("no", gateway.getNo());
        }
        if(!TextUtils.isEmpty(gateway.getDescription())){
            map.put("description", gateway.getDescription());
        }
        shService.updateGateway(map)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void addCurtain(Curtain curtain, MySubscriber<Result> mySubscriber){
        Map<String, Object> map = new HashMap<>();
        map.put("gatewayId", curtain.getGatewayId());
        map.put("device", curtain.getDevice());
        map.put("description", curtain.getDescription());
        shService.addCurtain(map)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void deleteCurtain(int curtainId, MySubscriber<Result> mySubscriber){
        shService.deleteCurtain(curtainId)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getAllCurtain(int gatewayId,MySubscriber<Result<List<Curtain>>> mySubscriber){
        shService.getAllCurtain(gatewayId)
                .compose(this.<Result<List<Curtain>>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void foldCurtain(int curtainId, int level, int speed,
                            MySubscriber<Result> mySubscriber){
        shService.foldCurtain(curtainId, level, speed)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void unfoldCurtain(int curtainId, int level, int speed,
                              MySubscriber<Result> mySubscriber){
        shService.unfoldCurtain(curtainId, level, speed)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void stopCurtain(int curtainId, MySubscriber<Result> mySubscriber){
        shService.stopCurtain(curtainId)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void addEnvirDevice(EnvirDevice device, MySubscriber<Result> mySubscriber){
        Map<String, Object> map = new HashMap<>();
        map.put("gatewayId", device.getGatewayId());
        map.put("device", device.getDevice());
        map.put("type", device.getType());
        map.put("description",device.getDescription());
        shService.addEnvirDevice(map)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void deleteEnvirDevice(int envirdeviceId, MySubscriber<Result> mySubscriber){
        shService.deleteEnvirDevice(envirdeviceId)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getAllEnvirDevice(int gatewayId,MySubscriber<Result<List<EnvirDevice>>> mySubscriber){
        shService.getAllEnvirDevice(gatewayId)
                .compose(this.<Result<List<EnvirDevice>>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getAllTempAndHum(int gatewayId, MySubscriber<Result<List<TempAndHum>>> mySubscriber){
        shService.getAllTempAndHum(gatewayId)
                .compose(this.<Result<List<TempAndHum>>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getSectionTemp(int envirdeviceId, Date start, Date end,
                               MySubscriber<Result<List<Temperature>>> mySubscriber){

        shService.getSectionTemp(envirdeviceId, start.getTime(), end.getTime())
                .compose(this.<Result<List<Temperature>>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getSectionHum(int envirdeviceId, Date start, Date end,
                              MySubscriber<Result<List<Humidity>>> mySubscriber){
        shService.getSectionHum(envirdeviceId, start.getTime(), end.getTime())
                .compose(this.<Result<List<Humidity>>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getLatestTemp(int envirdeviceId, MySubscriber<Result<Temperature>> mySubscriber){
        shService.getLatestTemp(envirdeviceId)
                .compose(this.<Result<Temperature>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getLatestHum(int envirdeviceId, MySubscriber<Result<Humidity>> mySubscriber){
        shService.getLatestHum(envirdeviceId)
                .compose(this.<Result<Humidity>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void airConditionerOn(MySubscriber<Result> mySubscriber){
        shService.airConditionerOn()
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void airConditionerOff(MySubscriber<Result> mySubscriber){
        shService.airConditionerOff()
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void addSecurityDevice(SecurityDevice device, MySubscriber<Result> mySubscriber){
        Map<String, Object> map = new HashMap<>();
        map.put("gatewayId", device.getGatewayId());
        map.put("type", device.getType());
        map.put("device", device.getDevice());
        map.put("description", device.getDescription());
        shService.addSecurityDevice(map)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void delSecurityDevice(int deviceId, MySubscriber<Result> mySubscriber){
        shService.delSecurityDevice(deviceId)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getAllSecurityDevice(int gatewayId,MySubscriber<Result<List<SecurityDevice>>> mySubscriber){
        shService.getAllSecurityDevice(gatewayId)
                .compose(this.<Result<List<SecurityDevice>>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getLatestSecurityWarning(int deviceId, MySubscriber<Result<Warning>> mySubscriber){
        shService.getLatestSecurityWarning(deviceId)
                .compose(this.<Result<Warning>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void addFireDevice(FireDevice device, MySubscriber<Result> mySubscriber){
        Map<String, Object> map = new HashMap<>();
        map.put("gatewayId", device.getGatewayId());
        map.put("type", device.getType());
        map.put("device", device.getDevice());
        map.put("description", device.getDescription());
        shService.addFireDevice(map)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void delFireDevice(int deviceId, MySubscriber<Result> mySubscriber){
        shService.delFireDevice(deviceId)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getAllFireDevice(int gatewayId, MySubscriber<Result<List<FireDevice>>> mySubscriber){
        shService.getAllFireDevice(gatewayId)
                .compose(this.<Result<List<FireDevice>>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getLatestFireWarning(int deviceId, MySubscriber<Result<Warning>> mySubscriber){
        shService.getLatestFireWarning(deviceId)
                .compose(this.<Result<Warning>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void addPump(Pump pump, MySubscriber<Result> mySubscriber){
        Map<String, Object> map = new HashMap<>();
        map.put("gatewayId", pump.getGatewayId());
        map.put("device", pump.getDevice());
        map.put("description", pump.getDescription());
        shService.addPump(map)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void delPump(int pumpId, MySubscriber<Result> mySubscriber){
        shService.delPump(pumpId)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getAllPump(int gatewayId, MySubscriber<Result<List<Pump>>> mySubscriber){
        shService.getAllPump(gatewayId)
                .compose(this.<Result<List<Pump>>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void addRainObserver(RainObserver rainObserver, MySubscriber<Result> mySubscriber){
        Map<String, Object> map = new HashMap<>();
        map.put("gatewayId", rainObserver.getGatewayId());
        map.put("device", rainObserver.getDevice());
        map.put("description", rainObserver.getDescription());
        shService.addRainObserver(map)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void delRainObserver(int rainObserverId, MySubscriber<Result> mySubscriber){
        shService.delRainObserver(rainObserverId)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getAllRainObserver(int gatewayId, MySubscriber<Result<List<RainObserver>>> mySubscriber){
        shService.getAllRainObserver(gatewayId)
                .compose(this.<Result<List<RainObserver>>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void startPump(int pumpId, int level,  MySubscriber<Result> mySubscriber){
        shService.startPump(pumpId, level)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void stopPump(int pumpId, MySubscriber<Result> mySubscriber){
        shService.stopPump(pumpId)
                .compose(this.<Result>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getAllSecurityWarning(int gatewayId, MySubscriber<Result<List<SecurityWarning>>> mySubscriber){
        shService.getAllSecurityWarning(gatewayId)
                .compose(this.<Result<List<SecurityWarning>>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getAllFireWarning(int gatewayId, MySubscriber<Result<List<FireWarning>>> mySubscriber){
        shService.getAllFireWarning(gatewayId)
                .compose(this.<Result<List<FireWarning>>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getSecurityDeviceById(int id, MySubscriber<Result<SecurityDevice>> mySubscriber){
        shService.getSecurityDeviceById(id)
                .compose(this.<Result<SecurityDevice>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getFireDeviceById(int id, MySubscriber<Result<FireDevice>> mySubscriber){
        shService.getFireDeviceById(id)
                .compose(this.<Result<FireDevice>>applySchedulers())
                .subscribe(mySubscriber);
    }

    public void getAllNotification(int userId, MySubscriber<Result<List<Notification>>> mySubscriber){
        shService.getAllNotification(userId)
                .compose(this.<Result<List<Notification>>>applySchedulers())
                .subscribe(mySubscriber);
    }

}
